package com.ruoyi.project.mobile.usersupply;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.uniquekey.IdGererateFactory;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.project.AppBeanInjector;
import com.ruoyi.project.system.address.service.IMemberAddressService;
import com.ruoyi.project.system.coinrecord.domain.HondaCoinRecord;
import com.ruoyi.project.system.coinrecord.service.IHondaCoinRecordService;
import com.ruoyi.project.system.goods.goods.domain.GoodsGoods;
import com.ruoyi.project.system.goods.goods.service.IGoodsGoodsService;
import com.ruoyi.project.system.goods.goodscard.card.dto.SupplyCardDto;
import com.ruoyi.project.system.goods.goodscard.card.service.IGoodsSupplyCardService;
import com.ruoyi.project.system.goods.goodscard.product.domain.SupplyCardProduct;
import com.ruoyi.project.system.goods.goodscard.product.dto.SupplyCardProductDto;
import com.ruoyi.project.system.goods.goodscard.product.service.ISupplyCardProductService;
import com.ruoyi.project.system.goods.goodscard.send.service.ISupplySendService;
import com.ruoyi.project.system.goodsclass.domain.GoodsClass;
import com.ruoyi.project.system.goodsclass.service.IGoodsClassService;
import com.ruoyi.project.system.hondaconfig.service.IHondaConfigService;
import com.ruoyi.project.system.member.domain.Member;
import com.ruoyi.project.system.member.enums.MemberStatus;
import com.ruoyi.project.system.member.service.IMemberService;
import com.ruoyi.project.system.order.order.enums.OrderPayType;
import com.ruoyi.project.system.paylog.domain.PayLog;
import com.ruoyi.project.system.paylog.service.IPayLogService;
import com.ruoyi.project.system.type.domain.GoodsType;
import com.ruoyi.project.system.type.service.IGoodsTypeService;
import com.ruoyi.project.system.userSupplyCard.domain.UserSupplyCard;
import com.ruoyi.project.system.userSupplyCard.service.IUserSupplyCardService;

/**
 * 功能：
 *
 * @author：dell
 * @create：2020/7/17 10:11
 * @version：2020 Version：1.0
 * @company：老屋新房 Created with IntelliJ IDEA
 */
@RestController
@RequestMapping("/api/supply")
public class ApiUserSupplyController extends BaseController {

	@Resource
	private IdGererateFactory idGererateFactory;

	@Autowired
	private IUserSupplyCardService userSupplyCardService;

	@Autowired
	private IMemberService memberService;

	@Autowired
	private IPayLogService payLogService;

	@Autowired
	private IGoodsTypeService goodsTypeService;

	@Autowired
	private IGoodsClassService goodsClassService;

	@Autowired
	private IGoodsGoodsService goodsGoodsService;

	@Autowired
	private IGoodsSupplyCardService goodsSupplyCardService;

	@Autowired
	private ISupplyCardProductService supplyCardProductService;

	@Autowired
	private ISupplySendService supplySendService;

	@Autowired
	private IMemberAddressService memberAddressService;

	@Autowired
	private IHondaConfigService hondaConfigService;

	@Autowired
	private IHondaCoinRecordService hondaCoinRecordService;

	@PostMapping("/wxpay")
	@Transactional
	public R wxpay(@RequestBody UserSupplyCard userSupplyCard, HttpServletRequest req){
		//判断商品是否下架
		GoodsGoods goodsGoods = this.goodsGoodsService.selectGoodsGoodsById(userSupplyCard.getGoodsId());
		if(goodsGoods==null||goodsGoods.getStatus()!=0){
			return R.error("商品 "+goodsGoods.getName()+" 已下架 供应卡不可购买");
		}
		//生成供应卡信息
		userSupplyCard.setSendTotal(0);
		userSupplyCard.setCreated(DateUtils.getNowDate());
		userSupplyCard.setSupplyNo(this.idGererateFactory.nextId().toString());
		userSupplyCard.setStatus(2);
		userSupplyCard.setIsUrge(0);
		userSupplyCard.setId(this.idGererateFactory.nextStringId());

		GregorianCalendar gregorianCalendar = new GregorianCalendar();
		gregorianCalendar.setTime(userSupplyCard.getCreated());
		gregorianCalendar.add(Calendar.DATE,userSupplyCard.getSumDay());
		userSupplyCard.setEndTime(gregorianCalendar.getTime());
		this.userSupplyCardService.insertUserSupplyCard(userSupplyCard);

		Member member = this.memberService.selectMemberById(userSupplyCard.getMemberId());

		HashMap<String, Object> map = new HashMap<>();
		//时间戳
		map.put("timeStamp",DateUtils.getNowDate().getTime()+"");
		//package

		//调用统一下单接口拿到prepay_id
		SortedMap<String, Object> date = new TreeMap<String,Object>();

		//返回用前端的date2
		SortedMap<String, Object> date2 = new TreeMap<String,Object>();
		date2.put("appId",AppBeanInjector.weixinConfig.getAppId());
		date2.put("timeStamp",DateUtils.getNowDate().getTime());
		date2.put("signType","MD5");

		date.put("appid",AppBeanInjector.weixinConfig.getAppId());
		date.put("attach","康来好生活订单");
		date.put("openid",member.getOpenid());
		date.put("body","康来好生活订单");
		date.put("mch_id",AppBeanInjector.weixinConfig.getMch_id());
		date.put("nonce_str",this.idGererateFactory.nextStringId());
		date.put("notify_url",AppBeanInjector.weixinConfig.getSupply_notify_url());
		date.put("out_trade_no",userSupplyCard.getSupplyNo()+"-"+this.idGererateFactory.nextStringId());
		date.put("spbill_create_ip",StringUtils.getRemoteAddr(req));
		float sessionmoney = Float.parseFloat(userSupplyCard.getPrice().toString());
		String finalmoney = String.format("%.2f", sessionmoney);
		finalmoney = finalmoney.replace(".", "");
		String newStr = finalmoney.replaceFirst("^0*", "");
		date.put("total_fee",newStr);
		date.put("trade_type","JSAPI");
		String perpayId = WeixinUtils.getPerpayId(date,date2);

		date2.put("package",FBSStringUtil.format("prepay_id={0}",perpayId));

		map.put("package",FBSStringUtil.format("prepay_id={0}",perpayId));
		//paySign 签名
		map.put("paySign",WeixinUtils.createSign(WeixinUtils.CHARSET,date2));
		//随机字符串
		map.put("nonceStr",date2.get("nonceStr"));


		//生成支付记录
		PayLog payLog = new PayLog();
		payLog.setOutTradeNo((String) date.get("out_trade_no"));
		payLog.setStatus(0);
		payLog.setType(1);
		payLog.setCreated(DateUtils.getNowDate());
		payLog.setMemberId(userSupplyCard.getMemberId());
		payLog.setResId(userSupplyCard.getId());
		payLog.setPrice(userSupplyCard.getPrice());
		this.payLogService.insertPayLog(payLog);

		return RFactory.generateR(map);

	}


	/**
	 * 支付成功的回调参数
	 * @param req
	 * @param res
	 * @return
	 */
	@PostMapping("/result")
	public Object weixinResult(HttpServletRequest req, HttpServletResponse res){
		try {
			InputStream inStream = req.getInputStream();
			ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = inStream.read(buffer)) != -1) {
				outSteam.write(buffer, 0, len);
			}
			System.out.println("~~~~~~~~~~~~~~~~付款成功~~~~~~~~~");
			outSteam.close();
			inStream.close();
			String result = new String(outSteam.toByteArray(), "utf-8");// 获取微信调用我们notify_url的返回信息
			Map<Object, Object> mapFromXml = WeixinUtils.doXMLParse(result);
			SortedMap<String ,String > sortedMap = new TreeMap();
			if (mapFromXml.get("result_code").toString().equalsIgnoreCase("SUCCESS")) {

				PayLog payLog = this.payLogService.selectPayLogByNo(mapFromXml.get("out_trade_no").toString());
				if(payLog.getStatus()==0){

					String supplyNo = mapFromXml.get("out_trade_no").toString().split("-")[0];
					UserSupplyCard userSupplyCard = this.userSupplyCardService.findByNo(supplyNo);
					if (userSupplyCard!=null){
						if (userSupplyCard.getStatus()!=2){
							return "fail";
						}
						//  验签成功后
						UserSupplyCard updateUserSupply = new UserSupplyCard();
						updateUserSupply.setId(userSupplyCard.getId());
						updateUserSupply.setStatus(0);
						this.userSupplyCardService.updateUserSupplyCard(updateUserSupply);
						//更新支付记录
						PayLog updatePayLog = new PayLog();
						updatePayLog.setId(payLog.getId());
						updatePayLog.setStatus(1);
						this.payLogService.updatePayLog(updatePayLog);
						//更新用户信息
						Member member = this.memberService.selectMemberById(payLog.getMemberId());
						Member updateMember = new Member();
						updateMember.setId(member.getId());
						updateMember.setOrderNum(member.getOrderNum()+1);
						this.memberService.updateMember(updateMember);
						//判断是否有推荐人 推荐人积分返还
						if(member.getIntroUser()!=null){
							Member introUser = this.memberService.selectMemberById(member.getIntroUser());
							//判断推荐人是否存在 状态是否正常
							if(introUser!=null&&introUser.getStatus()==MemberStatus.NORMAL.getValue()){
								//todo:获取下单返费比例
								// this.hondaConfigService.findAll().get(0).getReturning()
								BigDecimal returning = new BigDecimal(0);
								//计算返费积分
								BigDecimal returningCoin = payLog.getPrice().multiply(returning).multiply(new BigDecimal(0.01)).setScale(2,BigDecimal.ROUND_HALF_DOWN);
								//推荐人的积分增加
								Member updateIntro = new Member();
								updateIntro.setId(introUser.getId());
								updateIntro.setCoin(introUser.getCoin().add(returningCoin));
								updateIntro.setSumCoin(introUser.getSumCoin().add(returningCoin));
								this.memberService.updateMember(updateIntro);
								//推荐成功进行积分反馈
								HondaCoinRecord hondaCoinRecord = new HondaCoinRecord();
								hondaCoinRecord.setStatus(1);
								hondaCoinRecord.setMemberId(introUser.getId());
								hondaCoinRecord.setType(0);
								hondaCoinRecord.setGetType(1);
								hondaCoinRecord.setCreated(DateUtils.getNowDate());
								hondaCoinRecord.setNum(returningCoin);
								hondaCoinRecord.setResId(member.getId());
								this.hondaCoinRecordService.insertHondaCoinRecord(hondaCoinRecord);
							}
						}
					}else{
						sortedMap.put("return_code","FAIL");
						sortedMap.put("return_msg","签名失败");
						BufferedOutputStream out = new BufferedOutputStream(
								res.getOutputStream());
						out.write(parseXML(sortedMap).getBytes());
						out.flush();
						out.close();
						return "success";
						}
					}

				}

				sortedMap.put("return_code","SUCCESS");
				sortedMap.put("return_msg","OK");

				BufferedOutputStream out = new BufferedOutputStream(
						res.getOutputStream());
				out.write(parseXML(sortedMap).getBytes());
				out.flush();
				out.close();
			return "success";
		} catch (Exception e) {
			return "failure";
		}
	}


	//输出XML
	public String parseXML(Map map) {
		StringBuffer sb = new StringBuffer();
		sb.append("<xml>\n");
		Set es = map.entrySet();
		Iterator it = es.iterator();
		while(it.hasNext()) {
			Map.Entry entry = (Map.Entry)it.next();
			String k = (String)entry.getKey();
			String v = (String)entry.getValue();
			if(null != v && !"".equals(v) && !"appkey".equals(k)) {

				sb.append("<" + k +"><![CDATA[" + v + "]]></" + k + ">\n");
			}
		}
		sb.append("</xml>");
		return sb.toString();
	}


	/**
	 * 查询全部可用的类别
	 * @param uid
	 * @return
	 */
	@GetMapping("/types")
	public R supplyCardTypeList(@RequestParam String uid){
		GoodsType goodsType = new GoodsType();
		goodsType.setStatus(0);
		return RFactory.generateR(this.goodsTypeService.selectGoodsTypeList(goodsType));
	}

	/**
	 * 查询全部可用的类型
	 * @param uid
	 * @return
	 */
	@GetMapping("/class")
	public R supplyCardClassList(@RequestParam String uid){
		GoodsClass goodsClass = new GoodsClass();
		goodsClass.setStatus(0);
		return RFactory.generateR(this.goodsClassService.selectGoodsClassList(goodsClass));
	}

	@GetMapping("/goods")
	public R supplyCardGoodsList(@RequestParam String uid,@RequestParam String tid,@RequestParam String cid){
		GoodsGoods goodsGoods = new GoodsGoods();
		goodsGoods.setStatus(0);
		goodsGoods.setClassId(cid);
		goodsGoods.setTypeId(tid);
		return RFactory.generateR(this.goodsGoodsService.selectGoodsGoodsList(goodsGoods));
	}

	@GetMapping("/products")
	public R findSupplyProducts(@RequestParam String uid,@RequestParam String gid){
		SupplyCardDto byId = this.goodsSupplyCardService.findById(gid);

		if(byId==null){
			return R.error("该商品没有供应卡");
		}
		List<SupplyCardProductDto> cardProductDtos = this.supplyCardProductService.findBySId(byId.getId());
		for(SupplyCardProductDto supplyCardProductDto :cardProductDtos){
			supplyCardProductDto.setSendList(this.supplySendService.findListByPid(supplyCardProductDto.getId()));
		}
		return RFactory.generateR(cardProductDtos);
	}

	@GetMapping("address")
	public R supplyAddress(@RequestParam String uid){
		return RFactory.generateR(this.memberAddressService.findDefault(uid));
	}
}
